/*
 * xml_lib.c
 *
 *  Created on: 2011-6-26
 *      Author: vyouzhi
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <malloc.h>

#include "xml_lib.h"

char *set_xml(DICT_LINK *head){
	xmlDocPtr doc = NULL;       /* document pointer */
	xmlNodePtr root_node = NULL, node = NULL, node1 = NULL;/* node pointers */
	xmlDtdPtr dtd = NULL;       /* DTD pointer */
	char buff[256];
	int i=0;
	char dtdsub[] = {"xda.data"}, root[]={"data"};
	xmlChar *xmlbuff, *escaped;
	char *CharBuff;
	int buffersize;
	
	DICT_LINK *dict_link_run;
	DICT_ARRAY *dict_array_run;

	LIBXML_TEST_VERSION;
	xmlSubstituteEntitiesDefault(1);    
	xmlLoadExtDtdDefaultValue = 1; 
	doc = xmlNewDoc(BAD_CAST "1.0");
	root_node = xmlNewNode(NULL, BAD_CAST root);
	xmlDocSetRootElement(doc, root_node);

	dtd = xmlCreateIntSubset(doc, BAD_CAST root, NULL, BAD_CAST dtdsub);
	
	dict_link_run = head->next;
	while(dict_link_run != NULL){
		sprintf(buff, "Row%d", i);
		node = xmlNewChild(root_node, NULL, BAD_CAST buff, NULL);
		dict_array_run = dict_link_run->da;

		while(dict_array_run != NULL) {
			escaped =  xmlEncodeSpecialChars(doc, BAD_CAST dict_array_run->value);
			/*escaped =  xmlEncodeEntitiesReentrant(doc, BAD_CAST readCol->value);*/
			node1 = xmlNewChild(node, NULL, BAD_CAST dict_array_run->field, escaped);
			xmlFree(escaped);
			dict_array_run = dict_array_run->next;
		}
		dict_link_run = dict_link_run->next;
		i++;
	}


	if(i<1){
		CharBuff = NULL;
	}else{
		/*xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);*/
		xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
		/*xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);*/
		CharBuff = strdup((char *)xmlbuff);
		xmlFree(xmlbuff);
	}

	xmlFreeDoc(doc);

	/*xmlCleanupParser();*/
	xmlMemoryDump();

	return CharBuff;
}

char *decide(xmlNodePtr dcur, xmlDocPtr ddoc, const xmlChar *n){
	char *val = NULL;
	xmlChar *key;

	if ((!xmlStrcmp(dcur->name, n))){
		key = xmlNodeListGetString(ddoc, dcur->xmlChildrenNode, 1);
		if(key == NULL)return NULL;
		val = strdup((char *)key);
		free(key);
	}
	return val;
}

recv_xml *get_xml(char *docname, int doclen) {

	xmlDocPtr doc;
	xmlNodePtr cur;
	recv_xml *rxml; 
	char *xmlval;
	/*int len;*/
	
	doc = xmlParseMemory(docname, doclen);

	if (doc == NULL ) {
		fprintf(stderr,"Document not parsed successfully. \n");
		return NULL;
	}

	cur = xmlDocGetRootElement(doc);

	if (cur == NULL) {
		fprintf(stderr,"empty document\n");
		xmlFreeDoc(doc);
		return NULL;
	}

	if (xmlStrcmp(cur->name, (const xmlChar *) "sql")) {
		fprintf(stderr,"document of the wrong type, root node != story");
		xmlFreeDoc(doc);
		return NULL;
	}
	
	rxml = (struct recv_xml *)calloc(1, sizeof(struct recv_xml));
	bzero(rxml, sizeof(recv_xml));

	cur = cur->xmlChildrenNode;
	while (cur != NULL) {
		if((xmlval = decide(cur, doc, (const xmlChar *)"rw")) != NULL){
			rxml->rw = xmlval;	
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"sub")) != NULL){
			/*len = strlen(xmlval) + 10;
			rxml->sub = (char *)calloc(len, sizeof(char));
			bzero(rxml->sub, len);
			strcpy(rxml->sub, xmlval);*/
			rxml->sub = xmlval;
			/*free(xmlval);*/
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"key")) != NULL){
			rxml->key = xmlval;			
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"lastid")) != NULL){			
			rxml->lastid = atol(xmlval);
			free(xmlval);
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"extime")) != NULL){
			rxml->extime = atoi(xmlval);
			free(xmlval);
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"host")) != NULL){
			rxml->host = xmlval;
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"port")) != NULL){
			rxml->port = atoi(xmlval);
			free(xmlval);
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"returnid")) != NULL){
			rxml->returnid = atoi(xmlval);
			free(xmlval);
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"logname")) != NULL){
			rxml->logname = atoi(xmlval);
			free(xmlval);
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"id")) != NULL){
			rxml->id = atoi(xmlval);
			free(xmlval);
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"action")) != NULL){
			rxml->action = xmlval;
		}
		else if((xmlval = decide(cur, doc, (const xmlChar *)"type")) != NULL){
			rxml->type = atoi(xmlval);
			free(xmlval);
		}
		
		cur = cur->next;
	}

	xmlFreeDoc(doc);

	return rxml;
}
/* vim: set ts=4 sw=4: */
